from Tools import *
from Types import *
import Global
import time

def inputLimitedLengthString(message, length):
    while True:
        inStr = input(message)
        if len(inStr) > length:
            print("length out of range, limit 72 byte.")
            continue
        return inStr
    
def inputValidDatetimeStr(message):
    '''輸入時間字符串串~ 返回秒級時間戳戳~
    now可以代表當前時間（含有日期），today可以代表當前日期'''
    while True:
        print(message, end=" ")
        inStr = input("yyyy-mm-dd[ HH:MM] ")
        if inStr == "now":            
            return int(time.time())
        dateStr =  time.strftime('%Y-%m-%d',time.localtime(time.time()))
        inStr = inStr.replace('today', dateStr)
        try :
            t = time.strptime(inStr, "%Y-%m-%d %H:%M")
        except:
            try :
                t = time.strptime(inStr, "%Y-%m-%d")
            except:
                print("Invalid input, please input again.")
                continue
        return int(time.mktime(t))
    
def inputValidNumber(message):
    while True:
        inStr = input(message)
        try:
            num = int(inStr)
        except:
            print("Invalid input, please input again.")
            continue
        return num
    
def inputValidNumberRange(message, begin, end):
    '''讓用戶輸入begin和end閉區間之間的整數'''
    if end < begin:
        raise ValueError('end must >= begin! begin:%d end:%d'%(begin, end))
    while True:
        num = inputValidNumber(message)
        if num < begin or num > end:
            print("Invalid input, please input again.")
            continue
        return num

def inputValidNumberRangeOrEmpty(message, begin, end):
    '''讓用戶輸入begin和end閉區間之間的整數，或者回車
    如果輸入回車返回None，否則返回整數'''
    if end < begin:
        raise ValueError('end must >= begin! begin:%d end:%d'%(begin, end))
    while True:
        inStr = input(message)
        if inStr == '':
            return None
        try:
            num = int(inStr)
        except:
            print("Invalid input, please input again.")
            continue
        if num < begin or num > end:
            print("Invalid input, please input again.")
            continue
        return num

def inputValidNumberRangeOrSpecifiedCharactories(message, begin, end, charList):
    '''讓用戶輸入begin和end閉區間之間的整數，或者charList中包含的字符
    返回用戶合法的輸入'''
    pass

def inputAccountId(message):
    index = 1
    idIndex = [None]
    maxAccountIndex = len(Global.accounts)
    if maxAccountIndex <= 1:
        raise ValueError('THERE IS NO ACCOUNT')
    for id in range(1, maxAccountIndex):
        account = Global.accounts[id]
        if account.showable == False:
            continue
        print('(%d) %s'%(index, account.name))
        idIndex.append(id)
        index += 1
    index = inputValidNumberRange(message, 1, index - 1)
    return idIndex[index]

def inputCatId(message, cats):
    '''读取用户选择的CAT1，并返回对应的CAT1_ID'''
    indexId = [0]
    index = 1
    for item in cats:
        if item.showable == False:
            continue
        indexId.append(item.id)
        print('(%d) %s'%(index, item.name))
        index += 1
    index = inputValidNumberRange(message, 1, index-1)
    return indexId[index]

def inputPaymentCat2IdGuideByCat1Id(cat1s):
    '''返回一個包含2個元素的元組，分別為(cat1Id, cat2Id)'''
    cat1Id = inputCatId('SELECT A LEVEL 1 CATEGORY: ', cat1s[1:])
    cat2s = cat1s[cat1Id].cat2List
    cat2Id = inputCatId('SELECT A LEVEL 2 CATEGORY: ', cat2s)
    return (cat1Id, cat2Id)

def imputMoneyAmount(message):
    '''讀取用戶輸入的金額，單位為：元
    輸入的金額為整數或1位小數或2位小數，小數必須帶有整數部分
    返回數據的單位為：分'''
    yuan = '0'
    fen = '0'
    while True:
        inStr = input(message)
        numList = inStr.split('.')
        numListLen = len(numList)
        if numListLen == 1:
            yuan = numList[0]
        elif numListLen == 2:
            yuan = numList[0]
            fen = numList[1]
        else:
            print('INVALID INPUT, PLEASE INPUT AGAIN')
            continue
        if len(fen) > 2:
            print('PRECISION MUST LESS OR EQUAL THAN 2 BIT')
            continue
        try:
            yuan = int(yuan)
            fen = int(fen)
            if fen < 10:
                fen *= 10
        except:
            print('INVALID INPUT, PLEASE INPUT AGAIN')
            continue
        return yuan * 100 + fen

def inputRecordConfirm(record):
    '''只要record包含\_\_str\_\_方法就可以用這個函數，確認返回0，否則返回-1'''
    print('\nTHE NEW RECORD CONTENTS ARE:')
    print(record)
    print('')
    inputContent = input('PRESS ENTER TO CONFIRM, INPUT ANY THING TO CANCEL: ')
    if inputContent == '':
        return 0
    print('[CANCELED]')
    return -1

def inputIncomeRecord(cat1s):
    '''读取用户输入，成功返回IncomeRecord，否則返回None'''
    record = IncomeRecord()
    record.time = inputValidDatetimeStr("TIME: ")
    record.accountId = inputAccountId('PLEASE SELECT AN ACCOUNT:')
    record.cat1Id = inputCatId('SELECT CATEGORY: ', cat1s[1:])
    record.amount = imputMoneyAmount('AMOUNT: ')
    record.description = inputLimitedLengthString('DESCRIPTION: ', Global.MAX_DESCRIPTION_LENGTH)
    if inputRecordConfirm(record) == -1:
        return None
    return record

def inputPaymentRecord(cat1s):
    '''读取用户输入，成功返回PaymentRecord，否則返回None'''
    record = PaymentRecord()
    record.time = inputValidDatetimeStr("Input time: ")
    record.accountId = inputAccountId('PLEASE SELECT AN ACCOUNT:')
    ret = inputPaymentCat2IdGuideByCat1Id(cat1s)
    record.cat1Id = ret[0]
    record.cat2Id = ret[1]
    record.amount = imputMoneyAmount('AMOUNT: ')
    record.description = inputLimitedLengthString('DESCRIPTION: ', Global.MAX_DESCRIPTION_LENGTH)
    if inputRecordConfirm(record) == -1:
        return None
    return record


def inputTransferRecord(cat1s):
    '''读取用户输入，成功返回TransferRecord，否則返回None'''
    record = TransferRecord()
    record.cat1Id = inputCatId('SELECT CATEGORY: ', cat1s[1:])
    record.time = inputValidDatetimeStr("Input time: ")
    record.amount = imputMoneyAmount('AMOUNT: ')
    if record.cat1Id == TransferCat1Id.BorrowIn:
        record.srcAccountId = DefaultAccountId.Debt
        record.dstAccountId = DefaultAccountId.Cash
    elif record.cat1Id == TransferCat1Id.ReturnBack:
        record.srcAccountId = DefaultAccountId.Cash
        record.dstAccountId = DefaultAccountId.Debt
    elif record.cat1Id == TransferCat1Id.LendOut:
        record.srcAccountId = DefaultAccountId.Cash
        record.dstAccountId = DefaultAccountId.Redebt
    elif record.cat1Id == TransferCat1Id.ReturnIn:
        record.srcAccountId = DefaultAccountId.Redebt
        record.dstAccountId = DefaultAccountId.Cash
    elif record.cat1Id == TransferCat1Id.Other:
        record.srcAccountId = inputAccountId('PLEASE SELECT SROUCE ACCOUNT:')
        record.dstAccountId = inputAccountId('PLEASE SELECT DESTINATE ACCOUNT:')
        if record.srcAccountId == record.dstAccountId:
            print('ILLEGAL INPUT: SROUCE ACCOUNT IS SAME AS DESTINATE ACCOUNT')
            return None
    else:
        raise ValueError()
    record.description = inputLimitedLengthString('DESCRIPTION: ', Global.MAX_DESCRIPTION_LENGTH)
    if inputRecordConfirm(record) == -1:
        return None
    return record
 